﻿using System;
using System.Collections.Generic;
using System.Reflection;

public static partial class Tools
{
    /// <summary>
    /// 获取某类型在项目中的所有子类，并缓存
    /// </summary>
    public static List<Type> GetSubClassesOf<T>() where T : class
    {
        var type = typeof(T);
        if (!s_SubClassDict.TryGetValue(type.Name, out List<Type> types))
        {
            types = new List<Type>();
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assembly in assemblies)
            {
                var assemblyTypes = assembly.GetTypes();
                foreach (var assemblyType in assemblyTypes)
                {
                    if (type.IsAssignableFrom(assemblyType))
                    {
                        if (assemblyType.IsClass && !assemblyType.IsAbstract)
                        {
                            types.Add(assemblyType);
                        }
                    }
                }
            }
            s_SubClassDict.Add(type.Name, types);
        }
        return types;
    }
    private static Dictionary<string, List<Type>> s_SubClassDict = new Dictionary<string, List<Type>>();

    /// <summary>
    /// 获取所有标记为T属性的类，并缓存
    /// </summary>
    public static List<Type> GetAllTypesWithAttribute<T>() where T : Attribute
    {
        var type = typeof(T);
        if (!s_AttributeTypeDict.TryGetValue(type.Name, out var types))
        {
            types = new List<Type>();
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (var assmbly in assemblies)
            {
                var assemblyTypes = assmbly.GetTypes();
                foreach (var assemblyType in assemblyTypes)
                {
                    var attr = assemblyType.GetCustomAttribute<T>();
                    if (attr != null)
                    {
                        types.Add(assemblyType);
                    }
                }
            }
        }
        return types;
    }
    private static Dictionary<string, List<Type>> s_AttributeTypeDict = new Dictionary<string, List<Type>>();
}